package pdf;

import com.spire.pdf.PdfDocument;
import com.spire.pdf.PdfDocumentBase;
import com.spire.pdf.PdfPageBase;
import com.spire.pdf.automaticfields.PdfCompositeField;
import com.spire.pdf.automaticfields.PdfPageCountField;
import com.spire.pdf.automaticfields.PdfPageNumberField;
import com.spire.pdf.graphics.*;
import org.apache.pdfbox.multipdf.PDFMergerUtility;
import org.apache.pdfbox.multipdf.Splitter;
import org.apache.pdfbox.pdmodel.PDDocument;

import java.awt.*;
import java.awt.geom.Dimension2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.*;
import java.util.List;

/**
 * pdf的拆分和合并
 * https://blog.csdn.net/qq_40885034/article/details/116495904
 * 问题1：使用spire.pdf时，生成pdf文档时，第一页文档中会自动被添加水印【The document was created with Spire.PDF for .NET.】
 * 据说高版本 更是每页都会加
 * 解决办法：
 * 1.增加一页，然后再删除第一页（实测该方法不行，虽然能删除第一页的水页，但是不能删掉增加在最后的空白页，而是会删除中间的某一页）
 * https://blog.csdn.net/qq_21416547/article/details/108250016
 * 2.使用免费版，但免费版限制10页，后面的11页+就没有了：Spire.PDF Free version is limited to 10 pages of PDF.
 * https://blog.csdn.net/weixin_38211198/article/details/89192219
 * 3.遍历PDF页面，获取每个页面的文本，然后通过replace把水印替换为空字符串
 * https://blog.csdn.net/Mr_Malei/article/details/117809728
 */
public class PDFSplitMergeUtil {

    public static void main(String[] args) throws Exception {

        String filePath = "G:\\黑马资料java视频教程2021\\资料-2022MySQL数据库\\文档\\MySQL-运维篇.pdf";

        // pdfSplitByPDFBox(filePath);
        // pdfMergeByPDFBox(filePath.substring(0, filePath.lastIndexOf(".")));

        // 输出目录
        String outputDir = filePath.substring(0, filePath.lastIndexOf(".")) + "_spire" + File.separator;
        // pdfMultiSplitBySpire(filePath, 30, outputDir);
        pdfSingleSplitBySpire(filePath, outputDir);

        // 去除水印，方法有问题
        // 会丢页，并且倒数第二页依然会加上水印，只是可能看不出来，降低版本也不行
        // spireRemove(filePath + ".pdf", filePath + "_12.pdf");

        // addPdfPageNumbers(filePath + ".pdf", filePath + "_2.pdf");
    }

    /**
     * 拆分 Apache PDFBox
     * https://blog.csdn.net/Zhangsama1/article/details/123538548
     * https://blog.csdn.net/chenshibailian/article/details/86606786
     */
    public static void pdfSplitByPDFBox(String filePath) {
        File resource = new File(filePath);
        try {
            // 加载文档
            PDDocument doc = PDDocument.load(resource);
            // 创建一个拆分器对象
            Splitter split = new Splitter();
            // 设置从那页开始分割
            split.setStartPage(1);
            //设 置每个文件多少页，默认单页
            split.setSplitAtPage(30);
            // 分割文档
            // list中存放好被拆分的pdf对象 其中内容是pdf被切割后各部分
            List<PDDocument> docs = split.split(doc);
            int i = 1;
            // 生成分割文档
            filePath = filePath.substring(0, filePath.lastIndexOf(".")) + File.separator;
            File dir = new File(filePath);
            if (!dir.exists()) {
                // file.mkdir();
                // 可以创建多层目录文件夹
                dir.mkdirs();
            }
            for (PDDocument document : docs) {
                String fileName = filePath + i + ".pdf";
                File file = new File(fileName);
                if (!file.exists()) {
                    file.createNewFile();
                }
                FileOutputStream fos = new FileOutputStream(file);
                document.save(fos);
                document.close();
                i++;
            }
            doc.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 合并 Apache PDFBox
     * https://blog.csdn.net/Zhangsama1/article/details/123538548
     */
    public static void pdfMergeByPDFBox(String filePath) throws Exception {
        File file = new File(filePath);
        String[] pdfs;

        if (file.isDirectory()) {
            pdfs = file.list();
            if (pdfs.length > 0) {
                PDFMergerUtility mergePdf = new PDFMergerUtility();
                for (int i = 0; i < pdfs.length; i++) {
                    mergePdf.addSource(filePath + File.separator + pdfs[i]);
                }

                mergePdf.setDestinationFileName(filePath + File.separator + "合并.pdf");
                System.out.println("合并比较费时间,请等待个几分钟吧!");
                mergePdf.mergeDocuments();
                System.out.print("合并完成");
            }
        }
    }

    /**
     * 合并指定的pdf: Spire
     *
     * @param outFile
     * @param singlePdfNames
     * @throws Exception
     */
    public static void pdfMergeBySpire(String outFile, String... singlePdfNames) throws Exception {

        String outputFile = outFile;
        FileInputStream stream = null;
        InputStream[] streams = new InputStream[singlePdfNames.length];
        int index = 0;
        for (String fileName : singlePdfNames) {
            streams[index] = new FileInputStream(new File(fileName));
            index++;
        }

        // 合并PDF文档
        PdfDocumentBase doc = PdfDocument.mergeFiles(streams);

        // 保存文档
        doc.save(outputFile);
        doc.close();
    }

    /**
     * pdf按每页拆分
     */
    public static void pdfSingleSplitBySpire(String sourceFile, String outputDir) {
        //加载文档
        PdfDocument doc = new PdfDocument();
        doc.loadFromFile(sourceFile);

        //调用方法split()拆分，每一页拆分成一个pdf文件
        doc.split(outputDir + "{0}.pdf", 0);
        doc.close();
    }

    /**
     * 拆分多页: Spire
     *
     * @param sourceFile    分割的源文件
     * @param pageSplitNums 以此参数指定的页数为间隔拆分
     */
    public static void pdfMultiSplitBySpire(String sourceFile, Integer pageSplitNums, String outputDir) {

        // 加载需要拆分的PDF文档
        PdfDocument doc = new PdfDocument();
        doc.loadFromFile(sourceFile);

        // 新建第1个PDF文档1
        PdfDocument newpdf1 = new PdfDocument();
        PdfPageBase page = null;

        int start = 0;
        int temp = start;
        while (true) {
            try {
                if ((temp - start) == pageSplitNums) {
                    newpdf1.saveToFile(outputDir + start + ".pdf");
                    start = temp;
                    // 新new一个空文档
                    newpdf1 = new PdfDocument();
                }
                //越界时，捕捉到异常处理
                page = newpdf1.getPages().add(doc.getPages().get(temp).getSize(), new PdfMargins(0));
                doc.getPages().get(temp).createTemplate().draw(page, new Point2D.Float(0, 0));
                temp++;
            } catch (Exception e) {
                newpdf1.saveToFile(outputDir + start + ".pdf");
                break;
            }
        }
    }

    /**
     * 去除水印：spire
     * 方法不能用
     * https://blog.csdn.net/kewen_123/article/details/121025630
     */
    public static void spireRemoveBySpire(String oldFilePath, String newFilePath) {
        //加载PDF文档
        PdfDocument pdf = new PdfDocument();
        pdf.loadFromFile(oldFilePath);
        // 添加一个空白页，目的为了删除jar包添加的水印，后面再移除这一页
        // 会添加到最后面
        PdfPageBase page = pdf.getPages().add();

        // Spire.PDF：如何添加、删除PDF页面以及自定义文档属性
        // https://blog.csdn.net/weixin_40362806/article/details/107353117

        // 移除第一页 加的最后一页，删除的为什么是第一页？？？
        // pdf.getPages().removeAt(0);
        // pdf.getPages().remove(pdf.getPages().get(0));
        // 删除最后一页
        pdf.getPages().remove(pdf.getPages().get(pdf.getPages().getCount() - 1));

        // 添加一页空白页作为第1页
        // pdf.getPages().insert(0);
        // pdf.getPages().insert(1);
        // 反正在最后加一页，前面就会丢一页 感觉他这个是通过异常来中断生成水印的
        // pdf.getPages().removeAt(1);
        // pdf.getPages().removeAt(0);

        // pdf.getPages().add();
        // pdf.getPages().remove(pdf.getPages().get(0));
        // 就是他删的并不是最后一页
        // pdf.getPages().remove(pdf.getPages().get(pdf.getPages().getCount() - 1));

        // 保存为另外一个文档 保存并打开文档
        pdf.saveToFile(newFilePath);
        System.out.println("去除水印成功");
    }

    /**
     * 给pdf添加页码，并去掉水印
     * 去水印有问题
     * https://blog.csdn.net/qq_21416547/article/details/108250016
     */
    public static void addPdfPageNumbersBySpire(String oldFilePath, String newFilePath) {
        // 加载PDF文档
        PdfDocument pdf = new PdfDocument();
        pdf.loadFromFile(oldFilePath);
        // 添加一个空白页(最后一页)，目的为了删除jar包添加的水印，后面再移除这一页
        pdf.getPages().add();
        // 创建字体
        PdfTrueTypeFont font = new PdfTrueTypeFont(new Font("宋体", Font.PLAIN, 10), true);

        // 遍历文档中的页
        for (int i = 0; i < pdf.getPages().getCount(); i++) {
            Dimension2D pageSize = pdf.getPages().get(i).getSize();
            float y = (float) pageSize.getHeight() - 40;

            // 初始化页码域
            PdfPageNumberField number = new PdfPageNumberField();

            // 初始化总页数域
            PdfPageCountField count = new PdfPageCountField();

            // 创建复合域
            PdfCompositeField compositeField = new PdfCompositeField(font, PdfBrushes.getBlack(), "第{0}页 共{1}页", number, count);

            // 设置复合域内文字对齐方式
            compositeField.setStringFormat(new PdfStringFormat(PdfTextAlignment.Right, PdfVerticalAlignment.Top));

            // 测量文字大小
            Dimension2D textSize = font.measureString(compositeField.getText());

            // 设置复合域的在PDF页面上的位置及大小
            compositeField.setBounds(new Rectangle2D.Float(((float) pageSize.getWidth() - (float) textSize.getWidth()) / 2, y, (float) textSize.getWidth(), (float) textSize.getHeight()));

            // 将复合域添加到PDF页面
            compositeField.draw(pdf.getPages().get(i).getCanvas());
        }
        // 移除最后一页
        pdf.getPages().remove(pdf.getPages().get(pdf.getPages().getCount() - 1));
        // 保存为另外一个文档
        pdf.saveToFile(newFilePath);
        System.out.println("添加成功");
    }
}
